package cn.slipi.core.plugin.pre;

import cn.slipi.common.constants.Constants;
import cn.slipi.common.entity.PdrApi;
import cn.slipi.common.entity.RequestLog;
import cn.slipi.common.enums.PluginDetailEnum;
import cn.slipi.common.rule.custom.entity.GrayRelease;
import cn.slipi.common.rule.custom.entity.MatchCondition;
import cn.slipi.core.cache.ApiManager;
import cn.slipi.core.plugin.AbstractPlugin;
import cn.slipi.core.plugin.IPluginChain;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Objects;

/**
 * GrayReleasePlugin
 */
public class GrayReleasePlugin extends AbstractPlugin {

    private static final Logger LOGGER = LoggerFactory.getLogger(SignPlugin.class);

    private final ApiManager apiManager;

    public GrayReleasePlugin(final ApiManager apiManager) {
        super(apiManager);
        this.apiManager = apiManager;
    }

    @Override
    protected Mono<Void> doExecute(ServerWebExchange exchange, IPluginChain chain) {
        RequestLog requestLog = (RequestLog) exchange.getAttributes().get(Constants.REQUEST_LOG);

        MatchCondition requestCondition = (MatchCondition) exchange.getAttributes().get(Constants.GATEWAY_HEADER);
        PdrApi pdrApi = this.apiManager.getApiByCode(requestCondition.getApiCode());
        InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress();
        String clientIp = Objects.requireNonNull(remoteAddress).getAddress().getHostAddress();
        if (StringUtils.isNotBlank(clientIp)) {
            GrayRelease grayRelease = JSONObject.parseObject(pdrApi.getGrayRelease(), GrayRelease.class);
            if (Objects.nonNull(grayRelease) && Objects.nonNull(grayRelease.getIps()) && StringUtils.isNotBlank(grayRelease.getServer()) && grayRelease.getIps().length > 0) {
                boolean present = Arrays.stream(grayRelease.getIps()).anyMatch(ip -> StringUtils.equalsIgnoreCase(ip, clientIp));
                if (present) {
                    exchange.getAttributes().put(Constants.GRAY_RELEASE_LOAD_BALANCE, grayRelease.getServer());
                }
            }
        }

        requestLog.setGrayRelease("ok");
        exchange.getAttributes().put(Constants.REQUEST_LOG, requestLog);

        return chain.execute(exchange);
    }

    @Override
    public String getPluginPhase() {
        return PluginDetailEnum.GRAY_RELEASE.getPhase();
    }

    @Override
    public int getCode() {
        return PluginDetailEnum.GRAY_RELEASE.getCode();
    }

    @Override
    public String getName() {
        return PluginDetailEnum.GRAY_RELEASE.getName();
    }
}
